package com.wk.unittestshow;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;

import androidx.annotation.NonNull;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 声音波形的view <br>
 * 波形能左右移动的原理： <br>
 * 将自定义控件分成 listMaxSize 份，每份对应一个分贝值 ，
 * 根据分贝值的大小 来决定 线条的高度。
 * 分贝值更新引起ui更新，所以会形成从左向右效果。
 * mRecDataList.add(dbValue) ;
 * mRecDataList.remove(0) ;
 */

public class AudioWaveView extends View {
    private Bitmap mBackgroundBitmap;
    private Canvas mBackCanVans = new Canvas();
    /**波浪的画笔*/
    private Paint mPaint;
    /**绘制最终画面的 画笔*/
    private Paint mViewPaint;
    private final ArrayList<Integer> mRecDataList = new ArrayList<>();
    private int mScale = 1;
    /**控件总长度*/
    private int viewWidth;
    /**高度中间线 ，作为基准线*/
    private int mBaseLine;
    /**波形之间线与线的间隔*/
    private int smaleLineWidth = 0;
    /**一共画多少个小线条*/
    int listMaxSize = 0 ;
    /**是否画出基线*/
    private boolean mDrawBase = true;
    private boolean mPause = false;
    /**1  只画上面的波纹 ，2、上下都画*/
    private int mWaveCount = 2;
    private Context context ;

    public AudioWaveView(Context context) {
        super(context);
        init(context, null);
    }

    public AudioWaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public AudioWaveView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mBackgroundBitmap != null && !mBackgroundBitmap.isRecycled()) {
            mBackgroundBitmap.recycle();
        }
    }

    public void init(Context context, AttributeSet attrs) {
        // 防止因为xml可视化失败导致编译错误
        if (isInEditMode()){
            return;
        }

        this.context = context ;
        mPaint = new Paint();
        mPaint.setColor(Color.parseColor("#00ff33"));
        mViewPaint = new Paint();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        creatBackGroundBitmap();
    }

    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        if (visibility == VISIBLE && mBackgroundBitmap == null) {
            creatBackGroundBitmap();
        }
    }

    private void creatBackGroundBitmap() {
        ViewTreeObserver vto = getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                if (getWidth() > 0 && getHeight() > 0) {
                    smaleLineWidth = WkDeviceInforTool.getPixByDp( context ,2) ;
                    listMaxSize = getWidth() / smaleLineWidth ;

                    viewWidth = getWidth();
                    mBaseLine = getHeight() / 2;
                    mBackgroundBitmap = Bitmap.createBitmap( getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
                    mBackCanVans.setBitmap(mBackgroundBitmap);
                    mBackCanVans.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                    ViewTreeObserver vto = getViewTreeObserver();
                    // 移除绘制回调函数
                    vto.removeOnPreDrawListener(this);
                }
                return true;
            }
        });
    }

    private  void updateDrawParam(){
        ArrayList<Integer> dataList = new ArrayList<>();
        synchronized (mRecDataList) {

            if (mRecDataList.size() != 0) {
                try {
                    dataList = (ArrayList<Integer>) deepCopy(mRecDataList);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        if (!mPause) {
            // 获得最新缩放参数
            updateScale(dataList);
            if (mBackCanVans != null) {
                // 清除画布
                mBackCanVans.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                // 绘制基准线
                if (mDrawBase) {
                    mBackCanVans.drawLine(0, mBaseLine, viewWidth, mBaseLine, mPaint);
                }

                //绘制小线条形成波浪
                int dbSize = dataList.size();
                for (int i = 0, j = 0; i < dbSize; i++, j += smaleLineWidth) {
                    int dbValue = dataList.get(i);
                    drawDbLine(dbValue, j);
                }
                // 通知 重绘
                postInvalidate();
            }
        }
    }

    @Override
    protected void onDraw(Canvas c) {
        super.onDraw(c);
        if ( mBackgroundBitmap != null) {
            c.drawBitmap(mBackgroundBitmap, 0, 0, mViewPaint);
        }
    }

    /***
     * 根据当前分贝值对应的一小段 线条
     */
    private void drawDbLine(int dbValue, int smaleLineWidth) {
        int max =   mBaseLine - dbValue / mScale;
        if (mWaveCount == 2) {
            int min= mBaseLine  +  dbValue / mScale;
            mBackCanVans.drawLine(smaleLineWidth, mBaseLine, smaleLineWidth, max, mPaint);
            mBackCanVans.drawLine(smaleLineWidth, mBaseLine , smaleLineWidth,min , mPaint);
        } else {
            mBackCanVans.drawLine(smaleLineWidth, mBaseLine, smaleLineWidth, max, mPaint);
        }

    }

    /**
     * deepClone
     * @param src list
     * @return dest
     */
    public List deepCopy(ArrayList src) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(byteOut);
        out.writeObject(src);

        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
        ObjectInputStream in = new ObjectInputStream(byteIn);
        return (ArrayList) in.readObject();
    }

    /**
     *  根据当前块数据  更新 缩放音频显示的比例
     */
    private void updateScale(ArrayList<Integer> list) {
        int allMax = 0;
        for (int i = 0; i < list.size(); i++) {
            int sh = list.get(i);
            if (  sh > allMax) {
                allMax = sh;
            }
        }
        int curScale = allMax / mBaseLine;
        if (curScale > mScale) {
            mScale = curScale == 0  ? 1 : curScale ;
        }
    }


    /**
     * 停止绘制
     */
    public void stopView( ) {
        mRecDataList.clear();
        mBackCanVans.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
    }

    public void updateDataList(int dbValue ){
        if(mRecDataList.size() > listMaxSize){
            mRecDataList.add(dbValue) ;
            mRecDataList.remove(0) ;
        }else{
            mRecDataList.add(dbValue) ;
        }
        updateDrawParam();
    }
}
